package com.autumn.evaluator;

//
// * 可变的数据类型,表示解析结果、传入参数、变量、数组、数组集合等，即任何与解析引擎相关的数据类型
// * 在运算时自动变换类型，如整型与实数运算时，自动转换为实数
//

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;

import com.autumn.util.*;

/**
 * 表示可变数据类型
 */
public final class Variant implements Comparable<Variant>, Serializable {

	/**
	 * 序列号
	 */
	private static final long serialVersionUID = 5517290767856977754L;

	private Object value;
	private int type;
	private String name;
	public static Map<Class<?>, Object> BasicTypes = new HashMap<>();

	static {
		BasicTypes.put(String.class, "");
		BasicTypes.put(boolean.class, false);
		BasicTypes.put(Boolean.class, null);
		BasicTypes.put(byte.class, 0);
		BasicTypes.put(Byte.class, null);
		BasicTypes.put(short.class, 0);
		BasicTypes.put(Short.class, null);
		BasicTypes.put(int.class, 0);
		BasicTypes.put(Integer.class, null);
		BasicTypes.put(long.class, 0L);
		BasicTypes.put(Long.class, null);
		BasicTypes.put(Date.class, new Date());
		BasicTypes.put(BigDecimal.class, 0);
		BasicTypes.put(float.class, 0.0f);
		BasicTypes.put(Float.class, null);
		BasicTypes.put(double.class, 0.0d);
		BasicTypes.put(Double.class, null);
		BasicTypes.put(UUID.class, UUID.randomUUID());
	}

	/**
	 * 获取 Variant 默认值, IsNull 属性为 true;
	 */
	public static final Variant DEFAULT = new Variant();

	/**
	 * 实例化 Variant 类新实例
	 */
	public Variant() {
		this.name = null;
		this.value = null;
		this.type = VariantType.NULL;
	}

	/**
	 * 实例化 Variant 类新实例
	 *
	 * @param value
	 *            值
	 */
	public Variant(Object value) {
		this.name = null;
		if (value == null) {
			this.value = null;
			this.type = VariantType.NULL;
		} else {
			Class<?> vType = value.getClass();
			if (vType == Boolean.class || vType == boolean.class) {
				this.value = value;
				this.type = VariantType.BOOLEAN;
			} else if (vType == Byte.class || vType == byte.class) {
				this.value = value;
				this.type = VariantType.INTEGER;
			} else if (vType == Short.class || vType == short.class) {
				this.value = value;
				this.type = VariantType.INTEGER;
			} else if (vType == Integer.class || vType == int.class) {
				this.value = value;
				this.type = VariantType.INTEGER;
			} else if (vType == Long.class || vType == long.class) {
				long v = (long) value;
				if (v >= Long.MAX_VALUE) {
					this.value = value;
					this.type = VariantType.DOUBLE;
				} else {
					this.value = v;
					this.type = VariantType.INTEGER;
				}
			} else if (vType == Date.class) {
				this.value = value;
				this.type = VariantType.DATETIME;
			} else if (vType == BigDecimal.class) {
				this.value = value;
				this.type = VariantType.DECIMAL;
			} else if (vType == Float.class || vType == float.class) {
				this.value = value;
				this.type = VariantType.DOUBLE;
			} else if (vType == Double.class || vType == double.class) {
				this.value = value;
				this.type = VariantType.DOUBLE;
			} else if (vType == UUID.class) {
				this.value = value;
				this.type = VariantType.UUID;
			} else if (vType == String.class) {
				this.value = String.valueOf(value);
				this.type = VariantType.STRING;
			} else if (vType == Variant.class) {
				Variant v = (Variant) value;
				this.name = v.getName();
				this.value = v.getValue();
				this.type = v.getVariantType();
			} else {
				Variant[] vars = (Variant[]) ((value instanceof Variant[]) ? value : null);
				if (vars != null) {
					this.value = vars;
					this.type = VariantType.ARRAY;
				} else {
					this.value = null;
					this.type = VariantType.NULL;
				}
			}
		}
	}

	/**
	 * 实例化 Variant 类新实例
	 *
	 * @param name
	 *            名称
	 * @param value
	 *            值
	 */
	public Variant(String name, Variant[] value) {
		this.name = name;
		if (value != null) {
			this.value = value;
			this.type = VariantType.ARRAY;
		} else {
			this.value = null;
			this.type = VariantType.NULL;
		}
	}

	/**
	 * 获取或设置名称(一般主要应用于数组标识或数据库列名)
	 */
	public String getName() {
		return this.name;
	}

	public void setName(String value) {
		this.name = value;
	}

	/**
	 * 获取值
	 */
	public Object getValue() {
		return this.value;
	}

	/**
	 * 获取类型
	 *
	 * @return
	 */
	public int getVariantType() {
		return this.type;
	}

	/**
	 * 获取是否是空值
	 *
	 * @return
	 */
	public boolean isNull() {
		return this.getVariantType() == VariantType.NULL;
	}

	/**
	 * 获取是否是数值
	 *
	 * @return
	 */
	public boolean isNumber() {
		return this.getVariantType() == VariantType.INTEGER || this.getVariantType() == VariantType.DECIMAL
				|| this.getVariantType() == VariantType.DOUBLE;
	}

	/**
	 * 获取是否是字符窜
	 *
	 * @return
	 */
	public boolean isString() {
		return this.getVariantType() == VariantType.STRING;
	}

	/**
	 * 获取是否是日期时间
	 */
	public boolean isDateTime() {
		return this.getVariantType() == VariantType.DATETIME;
	}

	/**
	 * 获取是否是布尔值
	 *
	 * @return
	 */
	public boolean isBoolean() {
		return this.getVariantType() == VariantType.BOOLEAN;
	}

	/**
	 * 获取是否是UUID
	 *
	 * @return
	 */
	public boolean isUUID() {
		return this.getVariantType() == VariantType.UUID;
	}

	/**
	 * 获取是否是数组
	 *
	 * @return
	 */
	public boolean isArray() {
		return this.getVariantType() == VariantType.ARRAY;
	}

	/**
	 * 获取数字类型
	 *
	 * @param left
	 *            左值
	 * @param right
	 *            右值
	 * @return
	 */
	public static int getNumberType(Variant left, Variant right) {
		if (left.getVariantType() == VariantType.INTEGER && right.getVariantType() == VariantType.INTEGER) {
			return VariantType.INTEGER;
		} else if (left.getVariantType() == VariantType.DOUBLE || right.getVariantType() == VariantType.DOUBLE) {
			int leftType;
			int rightType;
			if (left.getVariantType() == VariantType.DOUBLE) {
				leftType = doubleConvert((Double) left.getValue());
			} else {
				leftType = left.getVariantType();
			}
			if (right.getVariantType() == VariantType.DOUBLE) {
				rightType = doubleConvert((Double) right.getValue());
			} else {
				rightType = right.getVariantType();
			}
			if (leftType == VariantType.DECIMAL && rightType == VariantType.DECIMAL) {
				return VariantType.DECIMAL;
			} else if (leftType == VariantType.INTEGER && rightType == VariantType.INTEGER) {
				return VariantType.INTEGER;
			} else if ((leftType == VariantType.DECIMAL && rightType == VariantType.INTEGER)
					|| (leftType == VariantType.INTEGER && rightType == VariantType.DECIMAL)) {
				return VariantType.DECIMAL;
			} else {
				return VariantType.DOUBLE;
			}
		} else {
			return VariantType.DECIMAL;
		}
	}

	/**
	 * 获取数字类型
	 *
	 * @param value
	 *            值
	 * @return
	 */
	public static int getNumberType(String value) {
		if (value.contains("E") || value.contains("e")) {
			return VariantType.DOUBLE;
		}
		String[] values = value.split("\\.");
		if (values.length > 1) {
			try {
				new BigDecimal(values[0]);
				return VariantType.DECIMAL;
			} catch (OverflowException e) {
				return VariantType.DOUBLE;
			}
		} else {
			try {
				Long.parseLong(values[0]);
				return VariantType.INTEGER;
			} catch (OverflowException e2) {
				try {
					new BigDecimal(values[0]);
					return VariantType.DECIMAL;
				} catch (OverflowException e3) {
					return VariantType.DOUBLE;
				}
			}
		}
	}

	/**
	 * DOUBLE 类型转换
	 *
	 * @param value
	 *            值
	 * @return
	 */
	public static int doubleConvert(double value) {
		if (Double.isNaN(value) || Double.isInfinite(value)) {
			return VariantType.DOUBLE;
		}
		return getNumberType(new Double(value).toString());
	}

	/**
	 * 运算
	 *
	 * @param left
	 *            左值
	 * @param right
	 *            右值
	 * @param delimiter
	 *            运算符
	 * @return
	 * @throws NotSupportException
	 *             不支持的操作
	 */
	private static Variant calc(double left, double right, String delimiter) {
		Variant value;
		if ("+".equals(delimiter)) {
			value = new Variant(left + right);
		} else if ("-".equals(delimiter)) {
			value = new Variant(left - right);
		} else if ("^".equals(delimiter)) {
			value = new Variant(Math.pow(left, right));
		} else if ("*".equals(delimiter)) {
			value = new Variant(left * right);
		} else {
			throw new NotSupportException();
		}
		return value;
	}

	/**
	 * 运算
	 *
	 * @param left
	 *            左值
	 * @param right
	 *            右值
	 * @param delimiter
	 *            运算符
	 * @return
	 * @throws NotSupportException
	 *             不支持的操作
	 */
	private static Variant calc(BigDecimal left, BigDecimal right, String delimiter) {
		Variant value;
		try {
			if ("+".equals(delimiter)) {
				value = new Variant(left.add(right));
			} else if ("-".equals(delimiter)) {
				value = new Variant(left.subtract(right));
			} else if ("^".equals(delimiter)) {
				value = new Variant(new BigDecimal(Math.pow(left.doubleValue(), right.doubleValue())));
			} else if ("*".equals(delimiter)) {
				value = new Variant(left.multiply(right));
			} else {
				throw new NotSupportException();
			}
		} catch (OverflowException e) {
			value = calc(left.doubleValue(), right.doubleValue(), delimiter);
		}
		return value;
	}

	/**
	 * 运算
	 *
	 * @param left
	 *            左值
	 * @param right
	 *            右值
	 * @param delimiter
	 *            运算符
	 * @return
	 * @throws NotSupportException
	 *             不支持的操作
	 */
	private static Variant calc(long left, long right, String delimiter) {
		Variant value;
		try {
			if ("+".equals(delimiter)) {
				value = new Variant(left + right);
			} else if ("-".equals(delimiter)) {
				value = new Variant(left - right);
			} else if ("^".equals(delimiter)) {
				value = new Variant(Math.round(Math.pow(left, right)));
			} else if ("*".equals(delimiter)) {
				value = new Variant(left * right);
			} else {
				throw new NotSupportException();
			}
		} catch (OverflowException e) {
			value = calc(new BigDecimal(left), new BigDecimal(right), delimiter);
		}
		return value;
	}

	/**
	 * 重载+运算符
	 *
	 * @param left
	 *            左值
	 * @param right
	 *            右值
	 * @return
	 */
	public static Variant add(Variant left, Variant right) {
		if (left.isNumber() && right.isNumber()) {
			int vt = getNumberType(left, right);
			if (vt == VariantType.INTEGER) {
				return calc(TypeUtils.toConvert(long.class, left.getValue()),
						TypeUtils.toConvert(long.class, right.getValue()), "+");
			} else if (vt == VariantType.DECIMAL) {
				return calc(new BigDecimal(left.getValue().toString()), new BigDecimal(right.getValue().toString()),
						"+");
			} else {
				return calc(TypeUtils.toConvert(double.class, left.getValue()),
						TypeUtils.toConvert(double.class, right.getValue()), "+");
			}
		} else {
			if (left.isDateTime() || right.isDateTime()) {
				// int dayms = 24 * 60 * 60 * 1000;
				if (left.isDateTime() && right.isNumber()) {
					return new Variant(new Date(((Date) left.getValue()).getTime() + ((long) right.getValue())));
				} else if (left.isNumber() && right.isDateTime()) {
					return new Variant(new Date((long) left.getValue() + ((Date) right.getValue()).getTime()));
				} else if (left.isDateTime() && right.isDateTime()) {
					return new Variant(
							new Date(((Date) left.getValue()).getTime() + ((Date) right.getValue()).getTime()));
				} else {
					return new Variant(String.valueOf(left) + String.valueOf(right));
				}
			} else {
				return new Variant(String.valueOf(left) + String.valueOf(right));
			}
		}
	}

	/**
	 * 重载++运算符
	 *
	 * @param value
	 *            值
	 * @return
	 * @throws NotSupportException
	 *             不支持的操作
	 */
	public static Variant increment(Variant value) {
		if (value.isNumber()) {
			if (value.getVariantType() == VariantType.INTEGER) {
				value = calc(TypeUtils.toConvert(long.class, value.getValue()), 1, "+");
			} else if (value.getVariantType() == VariantType.DECIMAL) {
				value = calc(new BigDecimal(value.getValue().toString()), new BigDecimal(1), "+");
			} else {
				value = calc(TypeUtils.toConvert(double.class, value.getValue()), 1.0, "+");
			}
		} else {
			throw new NotSupportException("非数值或日期时间类型不能进行减法运算。");
		}
		return value;
	}

	/**
	 * 重载 字符窜连接 运算符,VB连接表达式
	 *
	 * @param left
	 *            左值
	 * @param right
	 *            右值
	 * @return
	 * @throws NotSupportException
	 *             不支持的操作
	 */
	public static Variant join(Variant left, Variant right) {
		if ((left.isString() || left.isUUID() || left.isDateTime())
				&& (right.isString() || right.isUUID() || right.isDateTime())) {
			String v1;
			String v2;
			if (left.isDateTime()) {
				Date d = (Date) left.getValue();
				Time t = DateUtils.getTime(d);
				if (t.getHour() == 0 && t.getMinute() == 0 && t.getSecond() == 0) {
					v1 = DateUtils.dateFormat(d, "yyyy-MM-dd");
				} else {
					v1 = DateUtils.dateFormat(d, "yyyy-MM-dd HH:mm:ss");
				}
			} else {
				v1 = left.toString();
			}
			if (right.isDateTime()) {
				Date d = (Date) right.getValue();
				Time t = DateUtils.getTime(d);
				if (t.getHour() == 0 && t.getMinute() == 0 && t.getSecond() == 0) {
					v2 = DateUtils.dateFormat(d, "yyyy-MM-dd");
				} else {
					v2 = DateUtils.dateFormat(d, "yyyy-MM-dd HH:mm:ss");
				}
			} else {
				v2 = right.toString();
			}
			return new Variant(v1 + v2);
		}
		throw new NotSupportException("连接操作符只能用于字符串或日期时间连接。");
	}

	/**
	 * 重载-运算符
	 *
	 * @param left
	 *            左值
	 * @param right
	 *            右值
	 * @return
	 * @throws NotSupportException/
	 */
	public static Variant subtract(Variant left, Variant right) {
		if (left.isNumber() && right.isNumber()) {
			int vt = getNumberType(left, right);
			if (vt == VariantType.INTEGER) {
				return calc(TypeUtils.toConvert(long.class, left.getValue()),
						TypeUtils.toConvert(long.class, right.getValue()), "-");
			} else if (vt == VariantType.DECIMAL) {
				return calc(new BigDecimal(left.getValue().toString()), new BigDecimal(right.getValue().toString()),
						"-");
			} else {
				return calc(TypeUtils.toConvert(double.class, left.getValue()),
						TypeUtils.toConvert(double.class, right.getValue()), "-");
			}
		} else {
			if (left.isDateTime() || right.isDateTime()) {
				if (left.isDateTime() && right.isNumber()) {
					return new Variant(new Date(
							((Date) left.getValue()).getTime() - (TypeUtils.toConvert(long.class, right.getValue()))));
				} else if (left.isNumber() && right.isDateTime()) {
					return new Variant(new Date(
							(TypeUtils.toConvert(long.class, left.getValue())) - ((Date) right.getValue()).getTime()));
				} else if (left.isDateTime() && right.isDateTime()) {
					return new Variant(
							new Date(((Date) left.getValue()).getTime() - ((Date) right.getValue()).getTime()));
				} else {
					throw new NotSupportException("非数值或日期时间类型不能进行减法运算。");
				}
			} else {
				throw new NotSupportException("非数值或日期时间类型不能进行减法运算。");
			}
		}
	}

	/**
	 * 重载--运算符
	 *
	 * @param value
	 *            值
	 * @return
	 * @throws NotSupportException
	 *             不支持的操作
	 */
	public static Variant decrement(Variant value) {
		if (value.isNumber()) {
			if (value.getVariantType() == VariantType.INTEGER) {
				value = calc(TypeUtils.toConvert(long.class, value.getValue()), 1, "-");
			} else if (value.getVariantType() == VariantType.DECIMAL) {
				value = calc(new BigDecimal(value.getValue().toString()), new BigDecimal(1), "-");
			} else {
				value = calc(TypeUtils.toConvert(double.class, value.getValue()), 1.0, "-");
			}
		} else {
			throw new NotSupportException("非数值或日期时间类型不能进行减法运算。");
		}
		return value;
	}

	/**
	 * 重载-运算符
	 *
	 * @param value
	 *            值
	 * @return
	 * @throws NotSupportException
	 *             不支持的操作
	 */
	public static Variant unaryNegation(Variant value) {
		if (value.isNumber()) {
			if (value.getVariantType() == VariantType.INTEGER) {
				value.value = ((long) value.getValue()) * -1;
			} else if (value.getVariantType() == VariantType.DECIMAL) {
				value.value = ((BigDecimal) value.getValue()).multiply(new BigDecimal(-1));
			} else {
				value.value = ((double) value.getValue()) * -1.0;
			}
		} else {
			throw new NotSupportException("非数值或日期时间类型不能进行减法运算。");
		}
		return value;
	}

	/**
	 * 重载^运算符(乘方)
	 *
	 * @param left
	 *            左值
	 * @param right
	 *            右值
	 * @return
	 * @throws NotSupportException
	 *             不支持的操作
	 */
	public static Variant power(Variant left, Variant right) {
		if (left.isNumber() && right.isNumber()) {
			int vt = getNumberType(left, right);
			if (vt == VariantType.INTEGER) {
				return calc(TypeUtils.toConvert(long.class, left.getValue()),
						TypeUtils.toConvert(long.class, right.getValue()), "^");
			} else if (vt == VariantType.DECIMAL) {
				return calc(new BigDecimal(left.getValue().toString()), new BigDecimal(right.getValue().toString()),
						"^");
			} else {
				return calc(TypeUtils.toConvert(double.class, left.getValue()),
						TypeUtils.toConvert(double.class, right.getValue()), "^");
			}
		} else {
			throw new NotSupportException("非数值不能进行乘方运算。");
		}
	}

	/**
	 * 重载%运算符(取模)
	 *
	 * @param left
	 *            左值
	 * @param right
	 *            右值
	 * @return
	 * @throws NotSupportException
	 *             不支持的操作
	 */
	public static Variant modulo(Variant left, Variant right) {
		if (left.isNumber() && right.isNumber()) {
			int vt = getNumberType(left, right);
			if (vt == VariantType.INTEGER) {
				return new Variant(TypeUtils.toConvert(long.class, left.getValue())
						% TypeUtils.toConvert(long.class, right.getValue()));
			} else if (vt == VariantType.DECIMAL) {
				BigDecimal[] divideAndRemainder = (new BigDecimal(left.getValue().toString()))
						.divideAndRemainder(new BigDecimal(right.getValue().toString()));
				return new Variant(divideAndRemainder[1]);
			} else {
				return new Variant(TypeUtils.toConvert(double.class, left.getValue())
						% TypeUtils.toConvert(double.class, right.getValue()));
			}
		} else {
			throw new NotSupportException("非数值不能进行取模运算。");
		}
	}

	/**
	 * 重载*运算符
	 *
	 * @param left
	 *            左值
	 * @param right
	 *            右值
	 * @return
	 * @throws NotSupportException
	 *             不支持的操作
	 */
	public static Variant multiply(Variant left, Variant right) {
		if (left.isNumber() && right.isNumber()) {
			int vt = getNumberType(left, right);
			if (vt == VariantType.INTEGER) {
				return calc(TypeUtils.toConvert(long.class, left.getValue()),
						TypeUtils.toConvert(long.class, right.getValue()), "*");
			} else if (vt == VariantType.DECIMAL) {
				return calc(new BigDecimal(left.getValue().toString()), new BigDecimal(right.getValue().toString()),
						"*");
			} else {
				return calc(TypeUtils.toConvert(double.class, left.getValue()),
						TypeUtils.toConvert(double.class, right.getValue()), "*");
			}
		} else {
			if (left.isDateTime() || right.isDateTime()) {
				if (left.isDateTime() && right.isNumber()) {
					return new Variant(new Date(
							((Date) left.getValue()).getTime() * (TypeUtils.toConvert(long.class, right.getValue()))));
				} else if (left.isNumber() && right.isDateTime()) {
					return new Variant(new Date(
							(TypeUtils.toConvert(long.class, left.getValue())) * ((Date) right.getValue()).getTime()));
				} else if (left.isDateTime() && right.isDateTime()) {
					return new Variant(
							new Date(((Date) left.getValue()).getTime() * ((Date) right.getValue()).getTime()));
				} else {
					throw new NotSupportException("非数值或日期时间类型不能进行乘法运算。");
				}
			} else {
				throw new NotSupportException("非数值或日期时间类型不能进行乘法运算。");
			}
		}
	}

	/**
	 * 重载/运算符
	 *
	 * @param left
	 *            左值
	 * @param right
	 *            右值
	 * @return
	 * @throws NotSupportException
	 *             不支持的操作
	 */
	public static Variant divide(Variant left, Variant right) {
		if (left.isNumber() && right.isNumber()) {
			int vt = getNumberType(left, right);
			if (vt == VariantType.DOUBLE) {
				return new Variant(TypeUtils.toConvert(double.class, left.getValue())
						/ TypeUtils.toConvert(double.class, right.getValue()));
			} else {
				return new Variant((new BigDecimal(left.getValue().toString()))
						.divide(new BigDecimal(right.getValue().toString()), 30, BigDecimal.ROUND_HALF_UP));
			}
		} else {
			if (left.isDateTime() || right.isDateTime()) {
				if (left.isDateTime() && right.isNumber()) {
					return new Variant(new Date(
							((Date) left.getValue()).getTime() / (TypeUtils.toConvert(long.class, right.getValue()))));
				} else if (left.isNumber() && right.isDateTime()) {
					return new Variant(new Date(
							(TypeUtils.toConvert(long.class, left.getValue())) / ((Date) right.getValue()).getTime()));
				} else if (left.isDateTime() && right.isDateTime()) {
					return new Variant(
							new Date(((Date) left.getValue()).getTime() / ((Date) right.getValue()).getTime()));
				} else {
					throw new NotSupportException("非数值或日期时间类型不能进行除法运算。");
				}
			} else {
				throw new NotSupportException("非数值或日期时间类型不能进行除法运算。");
			}
		}
	}

	/**
	 * 重载==运算符
	 *
	 * @param left
	 *            左值
	 * @param right
	 *            右值
	 * @return
	 * @throws NotSupportException
	 *             不支持的操作
	 */
	public static boolean isEquality(Variant left, Variant right) {
		return left.compareTo(right) == 0;
	}

	/**
	 * 重载!=运算符
	 *
	 * @param left
	 *            左值
	 * @param right
	 *            右值
	 * @return
	 * @throws NotSupportException
	 *             不支持的操作
	 */
	public static boolean isInequality(Variant left, Variant right) {
		return left.compareTo(right) != 0;
	}

	/**
	 * 重载>运算符
	 *
	 * @param left
	 *            左值
	 * @param right
	 *            右值
	 * @return
	 * @throws NotSupportException
	 *             不支持的操作
	 */
	public static boolean greaterThan(Variant left, Variant right) {
		return left.compareTo(right) > 0;
	}

	/**
	 * 重载 小于 运算符
	 *
	 * @param left
	 *            左值
	 * @param right
	 *            右值
	 * @return
	 * @throws NotSupportException
	 *             不支持的操作
	 */
	public static boolean lessThan(Variant left, Variant right) {
		return left.compareTo(right) < 0;
	}

	/**
	 * 重载 >= 运算符
	 *
	 * @param left
	 *            左值
	 * @param right
	 *            右值
	 * @return
	 * @throws NotSupportException
	 *             不支持的操作
	 */
	public static boolean opGreaterThanOrEqual(Variant left, Variant right) {
		return left.compareTo(right) >= 0;
	}

	/**
	 * 重载 小于或等于 运算符
	 *
	 * @param left
	 *            左值
	 * @param right
	 *            右值
	 * @return
	 * @throws NotSupportException
	 *             不支持的操作
	 */
	public static boolean lessThanOrEqual(Variant left, Variant right) {
		return left.compareTo(right) <= 0;
	}

	/**
	 * 返回当前实例的 System.STRING
	 *
	 * @return
	 */
	@Override
	public String toString() {
		return this.toString(true);
	}

	/**
	 * 返回当前实例的 System.STRING
	 *
	 * @param removeZero
	 *            移除零
	 * @return
	 */
	public String toString(boolean removeZero) {
		if (this.isDateTime()) {
			Date d = (Date) this.value;
			Time t = DateUtils.getTime(d);
			// G 此处要换有日志
			if (t.getHour() == 0 && t.getMinute() == 0 && t.getSecond() == 0) {
				return DateUtils.dateFormat(d, "yyyy-MM-dd");
			} else {
				return DateUtils.dateFormat(d, "yyyy-MM-dd HH:mm:ss");
			}
		} else if (this.isNumber() && removeZero && this.getVariantType() == VariantType.DECIMAL) {
			String[] values = this.value.toString().split("\\.");
			StringBuilder v = new StringBuilder();
			v.append(values[0]);
			if (values.length > 1) {
				StringBuilder r = new StringBuilder();
				r.append(values[1]);
				while (r.length() > 0 && r.charAt(r.length() - 1) == '0') {
					r.deleteCharAt(r.length() - 1);
				}
				if (r.length() > 0) {
					v.append("." + r.toString());
				}
			}
			return v.toString();
		} else if (this.isNull()) {
			return "NULL";
		} else if (this.isArray()) {
			if (com.autumn.util.StringUtils.isNullOrBlank(this.getName())) {
				return "ARRAY[]";
			} else {
				return this.getName() + "(ARRAY[])";
			}
		}
		return this.value.toString();
	}

	/**
	 * 显示转换 为 UUID,等同于 (UUID)value
	 *
	 * @return
	 */
	public UUID toUUID() {
		return (UUID) this.getValue();
	}

	/**
	 * 显示转换为 Variant 数组,等同于 (Variant[])value
	 *
	 * @return
	 */
	public Variant[] toArray() {
		return (Variant[]) this.getValue();
	}

	/**
	 * 返回循环访问 Variant 的枚举数。
	 *
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public Iterator<Variant> getEnumerator() {
		if (this.isArray()) {
			Iterable<Variant> vars = (Iterable<Variant>) ((this.value instanceof Iterable) ? this.value : null);
			return vars.iterator();
		} else {
			throw new NotSupportException("非数组不支持迭代。");
		}
	}

	/**
	 * 返回一个值，该值指示此实例是否与指定的 Variant 值相等。
	 *
	 * @param value
	 *            要比较的对象，或为 null。
	 * @return
	 */
	@Override
	public boolean equals(Object value) {
		if (value == null) {
			return false;
		}
		if (value.getClass() == Variant.class) {
			Variant v = (Variant) value;
			return this.equals(v);
		} else {
			return false;
		}
	}

	/**
	 * 返回一个值，该值指示此实例是否与指定的 Variant 值相等。
	 *
	 * @param value
	 *            要与此实例进行比较的 Variant 值。
	 * @return
	 */
	public boolean equals(Variant value) {
		if (value.isNull() && this.isNull()) {
			return true;
		} else {
			if (value.value != null && this.value != null) {
				try {
					return this.compareTo(value) == 0;
				} catch (Exception e) {
					return false;
				}
			} else {
				return false;
			}
		}
	}

	/**
	 * 将此实例与指定对象进行比较并返回一个对二者的相对值的指示。
	 *
	 * @param value
	 *            要比较的对象，或为 null。
	 * @return 一个有符号数字，指示此实例和 value 的相对值。返回值说明小于零此实例小于 value。零此实例等于 value。大于零此实例大于
	 *         value。
	 * @throws ArgumentNullException
	 *             value 不是 Variant 。
	 * @throws IllegalArgumentException
	 *             不支持的比较引发的异常。
	 */
	// public int compareTo(Object value) {
	// if (value == null) {
	// throw new ArgumentNullException("value");
	// }
	// if (value.getClass() == Variant.class) {
	// Variant v = (Variant) value;
	// return this.compareTo(v);
	// } else {
	// throw new IllegalArgumentException(STRING.format("%s 不等于 Variant 类型",
	// "value"));
	// }
	// }

	/**
	 * 将此实例与指定的 Variant 位有符号整数进行比较并返回对其相对值的指示。
	 *
	 * @param value
	 *            要比较的 Variant 。
	 * @return 一个有符号数字，指示此实例和 value 的相对值。返回值说明小于零此实例小于 value。零此实例等于 value。大于零此实例大于
	 *         value。
	 * @throws RuntimeException
	 *             不支持的比较引发的异常。
	 */
	@Override
	public int compareTo(Variant value) {
		int to;
		if (this.isNull() && value.isNull()) {
			to = 0;
		} else if (this.isNull() && !value.isNull()) {
			to = -1;
		} else if (!this.isNull() && value.isNull()) {
			to = 1;
		} else if (this.isArray() && !value.isArray()) {
			to = 1;
		} else if (!this.isArray() && value.isArray()) {
			to = -1;
		} else if (this.isArray() && value.isArray()) {
			to = arrayCompareTo(this, value);
		} else if (this.isDateTime() && value.isDateTime()) {
			to = ((Date) this.getValue()).compareTo((Date) value.getValue());
		} else if (this.isString() && value.isString()) {
			to = this.toString().toLowerCase().compareTo(value.toString().toLowerCase());
		} else if (this.isUUID() && value.isUUID()) {
			to = ((UUID) this.getValue()).compareTo((UUID) value.getValue());
		} else if (this.isBoolean() && value.isBoolean()) {
			to = (TypeUtils.toConvert(boolean.class, this.getValue()))
					.compareTo(TypeUtils.toConvert(boolean.class, value.getValue()));
		} else if (this.isNumber() && value.isNumber()) // 数字
		{
			if (this.getVariantType() == VariantType.INTEGER && value.getVariantType() == VariantType.INTEGER) {
				to = (TypeUtils.toConvert(int.class, this.getValue()))
						.compareTo((TypeUtils.toConvert(int.class, value.getValue())));
			} else if (this.getVariantType() == VariantType.DECIMAL && value.getVariantType() == VariantType.DECIMAL) {
				to = (new BigDecimal(this.getValue().toString()))
						.compareTo((new BigDecimal(value.getValue().toString())));
			} else if (this.getVariantType() == VariantType.DOUBLE && value.getVariantType() == VariantType.DOUBLE) {
				to = (TypeUtils.toConvert(double.class, this.getValue()))
						.compareTo((TypeUtils.toConvert(double.class, value.getValue())));
			} else {
				int vt = Variant.getNumberType(this, value);
				if (vt == VariantType.INTEGER) {
					to = (TypeUtils.toConvert(long.class, this.getValue()))
							.compareTo((TypeUtils.toConvert(long.class, value.getValue())));
				} else if (vt == VariantType.DOUBLE) {
					to = (TypeUtils.toConvert(double.class, this.getValue()))
							.compareTo((TypeUtils.toConvert(double.class, value.getValue())));
				} else {
					to = (new BigDecimal(this.getValue().toString()))
							.compareTo(new BigDecimal(value.getValue().toString()));
				}
			}
		} else if ((this.isDateTime() && value.isString()) || (this.isString() && value.isDateTime())) {
			to = this.toString().toLowerCase().compareTo(value.toString().toLowerCase());
		} else if ((this.isNumber() && value.isDateTime()) || (this.isDateTime() && value.isNumber())
				|| (this.isBoolean() && value.isDateTime()) || (this.isDateTime() && value.isBoolean())) {
			if ((this.isNumber() && value.isDateTime()) || (this.isBoolean() && value.isDateTime())) {
				if (TypeUtils.toConvert(long.class, this.getValue()) == ((Date) value.getValue()).getTime()) {
					to = 0;
				} else if (TypeUtils.toConvert(long.class, this.getValue()) > ((Date) value.getValue()).getTime()) {
					to = 1;
				} else {
					to = -1;
				}
			} else {
				if (((Date) this.getValue()).getTime() == TypeUtils.toConvert(long.class, value.getValue())) {
					to = 0;
				} else if (((Date) this.getValue()).getTime() > TypeUtils.toConvert(long.class, value.getValue())) {
					to = 1;
				} else {
					to = -1;
				}
			}
		} else if ((this.isNumber() && value.isBoolean()) || (this.isBoolean() && value.isNumber())) {
			if ((TypeUtils.toConvert(double.class, this.getValue()))
					.compareTo(TypeUtils.toConvert(double.class, value.getValue())) == 0) {
				to = 0;
			} else if ((TypeUtils.toConvert(double.class, this.getValue()))
					.compareTo(TypeUtils.toConvert(double.class, value.getValue())) > 0) {
				to = 1;
			} else {
				to = -1;
			}
		} else {
			if (!this.isArray() && !this.isNull() && !value.isNull() && !value.isArray()) {
				to = this.toString().toLowerCase().compareTo(value.toString().toLowerCase());
			} else {
				throw new NotSupportException("不支持的比较。");
			}
		}
		return to;
	}

	/**
	 * 数组比较
	 *
	 * @param left
	 *            左值
	 * @param right
	 *            右值
	 * @return
	 */
	private int arrayCompareTo(Variant left, Variant right) {
		if (left.value == null && right.value == null) {
			return 0;
		} else if (left.value != null && right.value == null) {
			return 1;
		} else if (left.value == null && right.value != null) {
			return -1;
		} else {
			int length = left.getArrayLength();
			int arrayLength = right.getArrayLength();
			if (length > arrayLength) // 维数大于
			{
				return 1;
			} else if (length < arrayLength) // 维数小于
			{
				return -1;
			} else // 维数相同
			{
				if (length > 0 && arrayLength > 0) {
					Variant[] lVars = (Variant[]) left.value;
					Variant[] rVars = (Variant[]) right.value;
					return lVars[0].compareTo(rVars[0]);
				} else {
					return 0;
				}
			}
		}
	}

	/**
	 * 将 object 对象集合 转换为 Variant 数组
	 *
	 * @param items
	 *            项目集合
	 * @return
	 */
	public static Variant toVariant(Iterable<?> items) {
		if (items == null) {
			return new Variant(new Variant[] {});
		}
		Class<?> myType = null;
		for (Object item : items) {
			myType = item.getClass();
			break;
		}
		return toVariant(null, null, myType, items, true);
	}

	/**
	 * 将 T 对象集合 转换为 Variant 数组
	 * <p>
	 * <typeparam name="T">类型</typeparam>
	 *
	 * @param items
	 *            项目集合
	 * @return
	 */
	public static <T> Variant toVariant(Iterable<T> items, Class<T> clazz) {
		if (items == null) {
			throw new ArgumentNullException("Items");
		}
		return toVariant(null, null, clazz, items, true);
	}

	/**
	 * 将 object 对象集合 转换为 Variant 数组
	 *
	 * @param iterableItemType
	 *            对象的实际类型
	 * @param genericType
	 *            泛型Type
	 * @param type
	 *            类型
	 * @param items
	 *            项目集合
	 * @param throwError
	 *            抛异常
	 * @return
	 */
	public static Variant toVariant(Type iterableItemType, Type genericType, Class<?> type, Iterable<?> items,
			boolean throwError) {
		if (type == null) {
			throw new ArgumentNullException("type");
		}
		if (items == null) {
			return new Variant(new Variant[] {});
		}
		ArrayList<Variant> vCols = new ArrayList<Variant>();
		if (Variant.BasicTypes.containsKey(type)) {
			for (Object item : items) {
				if (item == null && type == String.class) {
					vCols.add(new Variant(""));
				} else {
					vCols.add(new Variant(item));
				}
			}
		} else {
			Type t = type.getGenericSuperclass();
			if (t == null) {
				t = genericType;
			}
			if (t instanceof ParameterizedType) {
				Type[] types = ((ParameterizedType) t).getActualTypeArguments();
				if (types.length == 1) {
					type = (Class<?>) types[0];
				} else {
					if (throwError) {
						throw new NotSupportException("只支持1个参数的泛型类型。");
					} else {
						type = null;
					}
				}
			}

			if (type == null) {
				type = (Class<?>) iterableItemType;
			}

			if (type != null) {
				Field[] properties = type.getDeclaredFields();
				for (Field p : properties) {
					p.setAccessible(true);
					if (p.isAccessible()) {
						ArrayList<Variant> vRows = new ArrayList<>();
						for (Object item : items) {
							Object value = null;
							try {
								value = p.get(item);
							} catch (IllegalAccessException e) {
								e.printStackTrace();
							}
							if (Variant.BasicTypes.containsKey(p.getType())) {
								if (value == null && p.getType() == String.class) {
									vRows.add(new Variant(""));
								} else {
									vRows.add(new Variant(value));
								}
							} else {
								if (Iterable.class.isAssignableFrom(p.getType())) {
									vRows.add(toVariant(null, p.getGenericType(), p.getType(),
											(value instanceof Iterable) ? (Iterable<?>) value : null, false));
								}
							}
						}
						vCols.add(new Variant(p.getName(), vRows.toArray(new Variant[vRows.size()])));
					}
				}
			}
		}
		return new Variant(vCols.toArray(new Variant[vCols.size()]));
	}

	/**
	 * 获取数组中的 Variant 对象
	 *
	 * @param index
	 *            索引
	 * @return
	 * @throws RuntimeException
	 *             完法转换。
	 */
	public Variant getArrayValue(int index) {
		if (this.isArray()) {
			Variant[] vars = (Variant[]) this.value;
			return vars[index];
		} else {
			throw new RuntimeException("非数组不支持索引。");
		}
	}

	/**
	 * 获取数组中的 Variant 维数(非数组返回 -1)
	 *
	 * @return
	 */
	public int getArrayLength() {
		if (this.isArray()) {
			return ((Variant[]) this.value).length;
		} else {
			return -1;
		}
	}

	@Override
	public Variant clone() {
		Variant varCopy = new Variant();

		varCopy.value = this.value;
		varCopy.type = this.type;
		varCopy.name = this.name;

		return varCopy;
	}
}
